package org.theqcp.wow.sim.gui.net;

import javax.swing.DefaultBoundedRangeModel;
import javax.swing.GroupLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.GroupLayout.SequentialGroup;

import org.theqcp.wow.api.wowarmory.WowArmory;
import org.theqcp.wow.model.api.ProgressListener;
import org.theqcp.wow.model.items.Equipment;
import org.theqcp.wow.model.mechanics.Attribute;
import org.theqcp.wow.model.mechanics.Slot;
import org.theqcp.wow.model.player.Player;
import org.theqcp.wow.sim.gui.DataPoint;
import org.theqcp.wow.sim.gui.EnhSimGUIFrame;
import org.theqcp.wow.sim.gui.ScrollingExceptionDialog;

public class ImportCharProgressFrame extends JFrame implements ProgressListener, Runnable {

    private static final long serialVersionUID = 5890494708968519899L;

    private static class PlayerLoader implements Runnable {
	protected final ProgressListener listener;
	protected final String realm, playerName;
	protected final EnhSimGUIFrame enhFrame;
	protected Player player = null;

	public PlayerLoader(EnhSimGUIFrame enhFrame, String realm, String playerName, ProgressListener listener) {
	    this.enhFrame = enhFrame;
	    this.realm = realm;
	    this.playerName = playerName;
	    this.listener = listener;
	}

	@Override
	public void run() {
	    WowArmory armory = new WowArmory();

	    try {
		player = armory.getPlayer(realm, playerName, listener);

		update();
	    } catch( Exception e ) {
		ScrollingExceptionDialog.startNewInstance(e);
	    }
	}

	private void update() {
	    player.recalc();
	    System.out.println(player);

	    Equipment mainHand = player.getEquipedItem(Slot.MAINHAND);
	    Equipment offHand = player.getEquipedItem(Slot.OFFHAND);

	    enhFrame.setDataPoint(DataPoint.race, player.getRace());

	    enhFrame.setDataPoint(DataPoint.mh_speed, mainHand.getStat(Attribute.SPEED));
	    enhFrame.setDataPoint(DataPoint.mh_dps, mainHand.getStat(Attribute.DPS));
	    enhFrame.setDataPoint(DataPoint.mh_crit, player.getEffectiveStat(Attribute.CRITPERCENT));
	    enhFrame.setDataPoint(DataPoint.mh_hit, player.getEffectiveStat(Attribute.HITPERCENT));
	    enhFrame.setDataPoint(DataPoint.mh_expertise_rating, player.getEffectiveStat(Attribute.EXPERTISERATING));

	    enhFrame.setDataPoint(DataPoint.oh_speed, offHand.getStat(Attribute.SPEED));
	    enhFrame.setDataPoint(DataPoint.oh_dps, offHand.getStat(Attribute.DPS));
	    enhFrame.setDataPoint(DataPoint.oh_crit, player.getEffectiveStat(Attribute.CRITPERCENT));
	    enhFrame.setDataPoint(DataPoint.oh_hit, player.getEffectiveStat(Attribute.HITPERCENT));
	    enhFrame.setDataPoint(DataPoint.oh_expertise_rating, player.getEffectiveStat(Attribute.EXPERTISERATING));

	    enhFrame.setDataPoint(DataPoint.ap, player.getEffectiveStat(Attribute.ATTACKPOWER));
	    enhFrame.setDataPoint(DataPoint.haste, player.getEffectiveStat(Attribute.HASTEPERCENT));
	    enhFrame.setDataPoint(DataPoint.armor_penetration, player.getEffectiveStat(Attribute.ARMORPENPERCENT));

	    enhFrame.setDataPoint(DataPoint.str, player.getEffectiveStat(Attribute.STRENGTH));
	    enhFrame.setDataPoint(DataPoint.agi, player.getEffectiveStat(Attribute.AGILITY));
	    enhFrame.setDataPoint(DataPoint.Int, player.getEffectiveStat(Attribute.INTELLECT));
	    enhFrame.setDataPoint(DataPoint.spi, player.getEffectiveStat(Attribute.SPIRIT));

	    enhFrame.setDataPoint(DataPoint.spellpower, player.getEffectiveStat(Attribute.SPELLPOWER));
	    // enhFrame.setDataPoint(DataPoint.spell_crit,
	    // player.getEffectiveStat(Attribute.CRITPERCENT));
	    // enhFrame.setDataPoint(DataPoint.spell_hit,
	    // player.getEffectiveStat(Attribute.SPELLPOWER));
	    enhFrame.setDataPoint(DataPoint.max_mana, player.getEffectiveStat(Attribute.MANA));
	    enhFrame.setDataPoint(DataPoint.mp5, player.getEffectiveStat(Attribute.MANAREGEN));
	}
    }

    public static void loadCharacter( EnhSimGUIFrame enhFrame, String realm, String playerName ) {
	ImportCharProgressFrame me = new ImportCharProgressFrame();
	try {
	    SwingUtilities.invokeLater(me);
	    SwingUtilities.invokeLater(new PlayerLoader(enhFrame, realm, playerName, me));
	} catch( Exception e ) {
	    ScrollingExceptionDialog.startNewInstance(e);
	}
    }

    protected final JTextField txtMessage = new JTextField(15);
    protected final JProgressBar prgBar = new JProgressBar();

    protected String lastStatusMessage = "Starting...";
    protected double progress = 0;

    protected ImportCharProgressFrame() {
	setupFrame();
    }

    protected void setupFrame() {
	prgBar.setModel(new DefaultBoundedRangeModel(0, 0, 0, 100));

	JPanel p = new JPanel();

	GroupLayout gl = new GroupLayout(p);

	SequentialGroup hGroup = gl.createSequentialGroup();
	SequentialGroup vGroup = gl.createSequentialGroup();

	hGroup.addGroup(gl.createParallelGroup().addComponent(txtMessage).addComponent(prgBar));

	vGroup.addGroup(gl.createParallelGroup().addComponent(txtMessage));
	vGroup.addGroup(gl.createParallelGroup().addComponent(prgBar));

	gl.setHorizontalGroup(hGroup);
	gl.setVerticalGroup(vGroup);

	p.setLayout(gl);

	add(p);

	update();
    }

    protected void update() {
	setTitle(String.format("Progress: %.1f%%", progress));

	txtMessage.setText(lastStatusMessage);

	if( progress <= 0 ) {
	    prgBar.setIndeterminate(true);
	} else {
	    prgBar.setIndeterminate(false);
	}

	prgBar.setValue((int) progress);
	System.out.printf("%3.1f%% => %s\n", progress, lastStatusMessage);
    }

    @Override
    public void updateProgress( double d ) {
	progress = d;

	update();
    }

    @Override
    public void complete() {
	dispose();
    }

    @Override
    public void fail() {
	dispose();
    }

    @Override
    public void updateProgress( double d, String message ) {
	progress = d;
	lastStatusMessage = message;

	update();
    }

    @Override
    public void run() {
	setDefaultCloseOperation(DISPOSE_ON_CLOSE);
	setLocationByPlatform(true);
	setAlwaysOnTop(true);
	setResizable(false);

	pack();
	setVisible(true);
    }

}
